home *** CD-ROM | disk | FTP | other *** search
- /*
- Sherlock delete program.
-
- source: sdel.c
- started: December 15, 1985
- versions:
- 1.0: July 21, 1988
- 1.0c: November 9, 1988 bug fix to sysnlput().
- 1.1: February 16, 1989 support for SL_DISABLE.
-
-
- PUBLIC DOMAIN SOFTWARE
-
- Sherlock, including the SPP, SDEL and SDIF programs, was placed in
- the public domain on June 15, 1991, by its author,
-
- Edward K. Ream
- 166 North Prospect Ave.
- Madison, WI 53705.
- (608) 257-0802
-
- Sherlock may be used for any commercial or non-commercial purpose.
-
-
- DISCLAIMER OF WARRANTIES
-
- Edward K. Ream (Ream) specifically disclaims all warranties,
- expressed or implied, with respect to this computer software,
- including but not limited to implied warranties of merchantability
- and fitness for a particular purpose. In no event shall Ream be
- liable for any loss of profit or any commercial damage, including
- but not limited to special, incidental consequential or other damages.
- */
-
- /*
- Define which compiler will be used.
- This should be done on the compiler command line.
-
- TURBOC use Turbo C compiler.
- MICRO_SOFT use version 4.0 of MicroSoft compiler on MS DOS.
- */
-
- /*
- Miscellaneous global constants.
- */
- #define ZERO (0)
- #define TRUE (1)
- #define FALSE (0)
- #define END_FILE 0x1a
- #define ERROR (-1)
- #define BAD_EXIT 1
- typedef int bool;
-
- /*
- Include subsidiary header files.
-
- SL.H MUST be included even if SL.C is not linked in.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <ctype.h>
- #include <string.h>
- #include <process.h>
-
- #include "sl.h"
-
- #define str_eq(a,b) (strcmp(a,b)==0)
- #define ishex(c) ((c>='0'&&c<='9') || (c>='a'&&c<='f') || (c>='A'&&c<='F'))
- #define isid1(c) (isalpha(c) || c=='_')
- #define isid2(c) (isalpha(c) || isdigit(c) || c=='_')
-
- #define SIGNON "SDEL v1.7: June 15, 1991"
-
- #ifdef SHERLOCK
- #define USAGE1 "usage: SDEL in out [options] ++/--tracepoint\n\n"
- #else
- #define USAGE1 "usage: SDEL in out [options]\n\n"
- #endif
-
- #define USAGE2 "-d retain SL_DISABLE macros\n"
- #define USAGE3 "-f <file> rename macros using a synonym file\n"
- #define USAGE4 "-i remove #include \"sl.h\" lines\n"
- #define USAGE5 "-n disallow nested comments\n"
- #define USAGE6 "-r retain SL_NAME macros\n"
- #define USAGE7 "-t allow trigraph translation\n"
- #define USAGE8 "-? print version number and exit\n"
-
-
- /*
- Spellings of special case macros.
- */
- char * r_void = "RETURN_VOID";
- char * s_disable = "SL_DISABLE"; /* new in v1.1 */
- char * s_name = "SL_NAME";
-
- /*
- Spellings of all return macros, except RETURN_VOID.
- */
- char * rmn_tab [] = {
-
- "RETURN_BOOL", "RETURN_CHAR", "RETURN_DOUBLE",
- "RETURN_FLOAT", "RETURN_INT", "RETURN_LONG",
- "RETURN_PTR", "RETURN_STRING", "RETURN_UINT",
- "RETURN_ULONG",
-
- /* End of table flag. */
- NULL
- };
-
- /*
- Spellings of all other macros.
- */
- char * mn_tab [] = {
-
- "SL_CLEAR", "SL_DUMP", "SL_INIT",
- "SL_OFF", "SL_ON", "SL_PARSE",
-
- "STAT", "STATB", "STATX",
- "TICK", "TICKB", "TICKN", "TICKX",
- "TRACE", "TRACEB", "TRACEN", "TRACEX",
- "TRACEP", "TRACEPB", "TRACEPN", "TRACEPX",
-
- NULL
- };
-
- /*
- Forward declarations.
-
- These lines will need to be modified or deleted when using old K & R
- compilers.
- */
- void delete (void);
- void out_all (void);
- void out_hnl (void);
- void out_lws (void);
- void do_arg (void);
- void do_comment (void);
- void do_id (bool nl_flag, bool multiple_flag);
- void do_pp (void);
- void do_string (void);
- void do_ws (void);
- bool is_return (char * name);
- bool is_sherlock (char * name);
- void get_id (char * buffer);
- void out_char (int c);
- void set_syn (char * id1, char * id2);
- char * str_alloc (char * string);
- void synonyms (void);
-
- void sysabort (void);
- void syspb (char c);
- void sysnext (void);
- void s_fillbuf (void);
- int sysn1 (void);
- int sysn2 (void);
- void sysiclose (void);
- int sysopen (char * name);
- int syscreat (char * name);
- void sysoclose (void);
- void sysnlput (void);
- void syscput (char);
- void syssput (char * s);
- void sysinit (void);
- void syscsts (void);
-
- void raw_close (int);
- int raw_creat (char * name);
- int raw_open (char * name);
- int raw_read (int handle, char * buffer, int n);
- int raw_write (int handle, char * buffer, int n);
- int syscstat (void);
-
- /* Global flags. */
- bool disable_flag = FALSE; /* TRUE if retain SL_DISABLE */
- bool include_flag = FALSE; /* TRUE if remove #include "sl.h" */
- bool name_flag = FALSE; /* TRUE if retain SL_NAME */
- bool nest_flag = TRUE;
- bool trigraph = FALSE;
-
- /* Global variables. */
- char * file = NULL;
- int line = 1; /* Current line number. */
- char ch; /* The NEXT character. */
- char last_ch = '@'; /* Previous non-blank char. */
- bool skipping = FALSE; /* TRUE if skipping output. */
- bool delete_flag = FALSE; /* Newline deleted flag. */
-
- #define MAX_SYMBOL 1000
- char symbol [MAX_SYMBOL];
- int held_nl; /* Number of held newlines. */
-
- char lws [MAX_SYMBOL]; /* Leading white space. */
- int lws_count = 0;
-
- char tws [MAX_SYMBOL]; /* Trailing white space. */
- int tws_count = 0;
-
- /* Main routine. Process command-line arguments. */
- main(int argc, char ** argv)
- {
- char *in = NULL, *out = NULL;
- char *arg;
- char *def;
- char *p1;
-
- /* These two calls MUST come before any others. */
- SL_INIT();
- SL_PARSE(argc, argv, "++", "--");
-
- /* Allow user to abort. */
- syscsts();
-
- TICKB("main");
-
- /* Always put out the sign on message. */
- printf("%s\n", SIGNON);
-
- /* Make first test for correct command line. */
- if (argc == 2 && str_eq(argv[1], "-?")) {
- sysabort();
- }
- else if (argc < 3) {
- printf("\n%s%s%s%s%s%s",
- USAGE2, USAGE3, USAGE4, USAGE5,
- USAGE6, USAGE7, USAGE8);
- sysabort();
- }
-
- /* Process all the arguments on the command line. */
- argc--;
- argv++;
- while (argc-- > 0) {
- arg = *argv++;
-
- if (str_eq(arg, "-d")) {
- disable_flag = TRUE;
- }
- else if (str_eq(arg, "-f")) {
- if (argc--) {
- arg = *argv++;
- file = arg;
- if (sysopen(arg) == FALSE) {
- printf("Can not open %s\n", arg);
- exit(BAD_EXIT);
- }
- synonyms();
- sysiclose();
- line = 1;
- }
- else {
- printf("Trailing -f\n");
- exit(BAD_EXIT);
- }
- }
- else if (str_eq(arg, "-i")) {
- /* Remove #include "sl.h" */
- include_flag = TRUE;
- }
- else if (str_eq(arg, "-n")) {
- /* Disallow nested comments. */
- nest_flag = FALSE;
- }
- else if (str_eq(arg, "-t")) {
- /* Allow trigraph translation. */
- trigraph = TRUE;
- }
- else if (str_eq(arg, "-r")) {
- /* Retain SL_NAME. */
- name_flag = TRUE;
- }
- else if (str_eq(arg, "-?")) {
- /* Ignore it. */
- ;
- }
- else if (in == NULL) {
- in = arg;
- }
- else if (out == NULL) {
- out = arg;
- }
- else {
- printf("Extra file argument: %s\n", arg);
- exit(BAD_EXIT);
- }
- }
-
- /* Make sure that both file arguments were provided. */
- if (in == NULL) {
- printf("Missing input, output file arguments.\n");
- sysabort();
- }
- else if (out == NULL) {
- printf("Missing output file argument.\n");
- sysabort();
- }
- else if (str_eq(in, out)) {
- printf("Can not copy input file to output file.");
- sysabort();
- }
-
- if (sysopen(out)) {
- printf("Output file: %s exists...\n", out);
- sysabort();
- }
- if (syscreat(out) == FALSE) {
- printf("Can not open %s\n", out);
- sysabort();
- }
- if (sysopen(in) == FALSE) {
- printf("Can not open %s\n", in);
- sysabort();
- }
-
- /* Copy the program, deleting all Sherlock macros. */
- delete();
-
- /* Close the output file. */
- sysoclose();
-
- TRACE("dump", sl_dump());
- RETURN_VOID("main");
- }
-
- /*
- Delete all calls to Sherlock macros, with any leading white space.
- */
- #define EXTRA_CLOSE\
- "Warning: Line %d, '*/' seen outside a comment.\n"
-
- void
- delete(void)
- {
- int i;
-
- TICKB("delete");
-
- if (ch == '#') {
- do_pp();
- }
- for(;;) {
- if (ch == END_FILE) {
- RETURN_VOID("delete");
- }
- else if (delete_flag) {
- delete_flag = FALSE;
- held_nl = 0;
-
- if (isalpha(ch) || ch == '_') {
- /* Leading id, multiple delete possible */
- do_id(TRUE, TRUE);
- }
- else if (ch == '#') {
- /* Allow preprocessor directives. */
- out_lws();
- do_pp();
- }
- else {
- out_lws();
- }
- }
- else if (ch == '\n') {
-
- /* Allow user to abort here. */
- syscsts();
-
- /*
- Count the number of newline and queue up
- the last leading white space.
- */
- skipping = TRUE;
-
- held_nl = 0;
- for (;;) {
- if (ch == '\n') {
- line++;
- held_nl++;
- sysnext();
- lws_count = 0;
- }
- else if (ch == ' ' || ch == '\t') {
- lws[lws_count++] = ch;
- sysnext();
- }
- else {
- break;
- }
- }
- skipping = FALSE;
-
- if (isalpha(ch) || ch == '_') {
- /* Leading id, no multiple delete */
- do_id(TRUE, FALSE);
- }
- else if (ch == '#') {
- out_hnl();
-
- /* Allow preprocessor directives. */
- do_pp();
- }
- else {
- out_all();
- }
- }
- else if (isalpha(ch) || ch == '_') {
- /* non-leading id, no multiple line. */
- do_id(FALSE, FALSE);
- last_ch = 'a';
- }
- else if (ch == '"' || ch == '\'') {
- do_string();
- last_ch = '"';
- }
- else if (ch == '/') {
- out_char(ch);
- sysnext();
- if (ch == '*') {
- out_char(ch);
- sysnext();
- do_comment();
- }
- else {
- last_ch = '/';
- }
- }
- else if (ch == '*') {
- out_char(ch);
- sysnext();
- if (ch == '/') {
- printf(EXTRA_CLOSE, line);
- out_char(ch);
- sysnext();
- }
- else {
- last_ch = '*';
- }
- }
- else {
- STAT("v_default");
- last_ch = ch;
- out_char(ch);
- sysnext();
- }
- }
- }
-
- /* Output all queued white space and newlines. */
- void
- out_all(void)
- {
- int i;
-
- out_hnl();
- out_lws();
- }
-
- /* Output held newlines. */
- void
- out_hnl(void)
- {
- int i;
-
- /* Output queued newlines. */
- for (i = 0; i < held_nl; i++) {
- sysnlput();
- }
- held_nl = 0;
- }
-
- /* Output leading white space. */
- void
- out_lws(void)
- {
- int i;
-
- /* Output leading white space. */
- for (i = 0; i < lws_count; i++) {
- out_char(lws [i]);
- }
- lws_count = 0;
- }
-
- /*
- Handle all remaining actual arguments to a Sherlock macro.
- The macro should end with a right paren and a semicolon.
- */
- #define EOF_IN_MACRO\
- "Unexpected End of File inside a Sherlock macro starting at line: %d.\n"
- #define NEED_SEMI\
- "Semicolon expected after Sherlock macro starting at line %d.\n"
-
- void
- do_arg(void)
- {
- int level;
- int start;
-
- TICKB("do_arg");
- TRACE("v", syssput("<BEGIN ARG>"));
-
- level = 1;
- start = line;
-
- for (;;) {
- do_ws();
- if (ch == END_FILE) {
- printf(EOF_IN_MACRO, start);
- RETURN_VOID("do_arg");
- }
- else if (ch == '(') {
- level++;
- out_char(ch);
- sysnext();
- }
- else if (ch == ')') {
- level--;
- if (level == 0) {
- TRACE("v", syssput("<END ARG>"));
- RETURN_VOID("do_arg");
- }
- else {
- out_char(ch);
- sysnext();
- }
- }
- else if (ch == '\n') {
- line++;
- if (!skipping) {
- sysnlput();
- }
- sysnext();
- }
- else if (ch == '"' || ch == '\'') {
- do_string();
- }
- else {
- out_char(ch);
- sysnext();
- }
- }
- }
-
- /*
- Handle a comment, including the closing, but not opening delim.
- */
-
- #define EOF_IN_COMMENT\
- "Unexpected End of File inside a comment starting at line: %d.\n"
- #define WARN_NESTED_COMMENT\
- "Line: %d, Warning: '/*' in comment ignored.\n"
-
- void
- do_comment(void)
- {
- int level;
- int start;
-
- TICKB("do_comment");
- TRACE("v", syssput("<BEGIN COMMENT>"));
-
- start = line;
- level = 1;
-
- for (;;) {
- if (ch == END_FILE) {
- printf(EOF_IN_COMMENT, start);
- RETURN_VOID("do_comment");
- }
- else if (ch == '/') {
- out_char(ch);
- sysnext();
- if (ch == '*') {
- out_char(ch);
- sysnext();
- if (nest_flag) {
- level++;
- }
- else {
- printf(WARN_NESTED_COMMENT, line);
- }
- }
- }
- else if (ch == '*') {
- out_char(ch);
- sysnext();
- if (ch == '/') {
- out_char(ch);
- sysnext();
- level--;
- if (level == 0) {
- TRACE("v", syssput("<END COMMENT>"));
- RETURN_VOID("do_comment");
- }
- }
- }
- else if (ch == '\n') {
- line++;
- if (!skipping) {
- sysnlput();
- }
- sysnext();
- }
- else {
- out_char(ch);
- sysnext();
- }
- }
- }
-
- /*
- Handle an identifier.
- nl_flag: True if the id is the first non-white space of the line.
- */
- #define NEED_OPEN\
- "Line %d: Open parenthesis expected after Sherlock macro.\n"
- #define NEED_NAME\
- "Line %d: Tracepoint name expected after Sherlock macro.\n"
- #define NEED_COMMA\
- "Line %d: Comma expected after tracepoint name in Sherlock macro.\n"
- #define EOF_IN_ARG\
- "Line %d: Unexpected End of File in Sherlock macro.\n"
-
- void
- do_id(bool nl_flag, bool multiple_flag)
- {
- int start;
- int i;
-
- TICKB("do_id");
-
- /* Get the id into symbol[]. */
- get_id(symbol);
-
- if (str_eq(symbol, r_void)) {
- start = line;
-
- /* Output all queued newlines and leading white space. */
- out_all();
-
- /* Translate RETURN_VOID to return */
- syssput("return");
-
- skipping = TRUE;
-
- do_ws();
- if (ch == '(') {
- sysnext();
- }
- else {
- printf(NEED_OPEN, line);
- }
-
- do_arg();
- if (ch == ')') {
- /* Skip the trailing closing paren. */
- sysnext();
- }
- do_ws();
-
- skipping = FALSE;
-
- if (ch == ';') {
- out_char(ch);
- sysnext();
- }
- else {
- printf(NEED_SEMI, start);
- }
- }
- else if (is_return(symbol)) {
- start = line;
-
- /* Output queued newlines and leading white space. */
- out_all();
-
- /* Translate RETURN_xxx to return */
- syssput("return");
-
- do_ws();
- if (ch == '(') {
- sysnext();
- }
- else {
- printf(NEED_OPEN, line);
- }
-
- skipping = TRUE;
-
- /* We can't demand a string here. An array is OK too. */
- do_ws();
-
- while (ch != ',' && ch != END_FILE) {
- sysnext();
- }
- if (ch == ',') {
- sysnext();
- }
- else {
- printf(EOF_IN_ARG, line);
- RETURN_VOID("do_id");
- }
-
- /* Copy the argument. */
- skipping = FALSE;
-
- do_arg();
- if (ch == ')') {
- /* Skip the trailing closing paren. */
- sysnext();
- }
- do_ws();
- if (ch == ';') {
- out_char(ch);
- sysnext();
- }
- else {
- printf(NEED_SEMI, start);
- }
- }
- else if (is_sherlock(symbol)) {
- start = line;
-
- /* Throw away all saved white space. */
- if (nl_flag) {
- held_nl = 0;
- lws_count = 0;
- }
- else {
- out_all();
- }
- skipping = TRUE;
-
- do_ws();
- if (ch == '(') {
- sysnext();
- }
- else {
- printf(NEED_OPEN, line);
- }
- do_arg();
- if (ch == ')') {
- sysnext();
- }
- if (ch == ';') {
- sysnext();
- }
- else {
- printf(NEED_SEMI, start);
- }
-
- skipping = FALSE;
-
- if (!nl_flag) {
- RETURN_VOID("do_id");
- }
-
- /* Save trailing white space. */
- while (ch == ' ' || ch == '\t') {
- tws [tws_count++] = ch;
- sysnext();
- }
-
- if (ch != '\n') {
- /* Change everything to one newline. */
- sysnlput();
- for (i = 0; i < tws_count; i++) {
- out_char(tws[i]);
- }
- RETURN_VOID("do_id");
- }
-
- /* Discard trailing white space. */
- tws_count = 0;
-
- /* Indicate at least one newline was deleted. */
- delete_flag = TRUE;
-
- /* Discard all newlines and all leading white space. */
- while (ch == '\n') {
- sysnext();
- lws_count = 0;
- while (ch == ' ' || ch == '\t') {
- lws[lws_count++] = ch;
- sysnext();
- }
- }
-
- /*
- Let the main line handle the newline so that
- leading white space will be handled properly.
- */
- if (!multiple_flag) {
- if (ch != '}' && last_ch != '{') {
- sysnlput();
- sysnlput();
- }
- else {
- sysnlput();
- }
- }
- skipping = FALSE;
- }
- else {
- out_all();
- syssput(symbol);
- }
- skipping = FALSE;
- RETURN_VOID("do_id");
- }
-
- /*
- Handle a preprocessor directive.
- */
- void
- do_pp(void)
- {
- int old_skipping;
-
- TICKB("do_pp");
- TRACE("v", syssput("<BEGIN PP>"));
-
- old_skipping = skipping;
- skipping = FALSE;
-
- for (;;) {
- do_ws();
- if (ch == END_FILE) {
- skipping = old_skipping;
-
- TRACE("v", syssput("<END PP>"));
- RETURN_VOID("do_pp");
- }
- else if (ch == '\\') {
- out_char(ch);
- sysnext();
- if (ch == '\n') {
- line++;
- sysnlput();
- sysnext();
- }
- }
- else if (ch == '\n') {
- skipping = old_skipping;
-
- /*
- Let the main line handle the newline so
- consecutive directives will be recognized.
- */
- TRACE("v", syssput("<END PP>"));
- RETURN_VOID("do_pp");
- }
- else if (ch == '"' || ch == '\'') {
- do_string();
- }
- else {
- out_char(ch);
- sysnext();
- }
- }
- }
-
- /*
- Handle a string, including the opening and closing delimiters.
- */
- #define EOF_IN_STRING\
- "Unexpected End of File inside string starting at line: %d.\n"
- #define EOF_IN_CHAR\
- "Unexpected End of File inside character constant starting at line: %d.\n"
- #define RUN_ON_STRING\
- "Run on string: newline in string starting at line %d.\n"
-
- void
- do_string(void)
- {
- int delim;
- int start;
- int i;
-
- TICKB("do_string");
- TRACE("v", syssput("<START STRING>"));
-
- start = line;
- delim = ch;
-
- out_char(ch);
- sysnext();
-
- for (;;) {
- if (ch == delim) {
- out_char(ch);
- sysnext();
-
- TRACE("v", syssput("<END STRING>"));
- RETURN_VOID("do_string");
- }
- else if (ch == END_FILE) {
-
- if (ch == '"') {
- printf(EOF_IN_STRING, start);
- }
- else {
- printf(EOF_IN_CHAR, start);
- }
- RETURN_VOID("do_string");
- }
-
- else if (ch == '\n') {
- line++;
- sysnext();
- if (!skipping) {
- sysnlput();
- }
- printf(RUN_ON_STRING, start);
- RETURN_VOID("do_string");
- }
- else if (ch == '\\') {
- /* Escape sequence. */
-
- STAT("v_esc");
-
- out_char(ch);
- sysnext();
- if (ch == '\n') {
- /* Strings eat directives. */
- line++;
- sysnext();
- if (!skipping) {
- sysnlput();
- }
- }
- else if (ch == 'x') {
- /* 3-digit hex escape sequence. */
- out_char(ch);
- sysnext();
- for (i = 0; i < 3 && ishex(ch); i++) {
- out_char(ch);
- sysnext();
- }
- }
- else if (ch >= '0' && ch <= '9') {
- /* Octal escape sequence. */
- for (i = 0; i < 3 && ch >= '0' && ch <= '9'; i++) {
- out_char(ch);
- sysnext();
- }
- }
- else if (ch != END_FILE) {
- out_char(ch);
- sysnext();
- }
- }
- else {
- out_char(ch);
- sysnext();
- }
- }
- }
-
- /*
- Handle white space, including comments.
- */
- void
- do_ws(void)
- {
- TICKB("do_ws");
-
- for (;;) {
- if (ch == ' ' || ch == '\t') {
- out_char(ch);
- sysnext();
- }
- else if (ch == '/') {
- out_char(ch);
- sysnext();
- if (ch == '*') {
- do_comment();
- }
- }
- else {
- RETURN_VOID("do_ws");
- }
- }
- }
-
- /*
- Get an identifier from the input file into the buffer.
- */
- void
- get_id(char * buffer)
- {
- int i;
-
- i = 0;
- while (isid2(ch)) {
- buffer[i++] = ch;
- sysnext();
- }
- buffer[i] = '\0';
-
- TRACEP("get_id", printf("<%s>\n", buffer));
- }
-
- /* Return TRUE if name is a Sherlock RETURN_xxx macro except RETURN_VOID. */
- bool
- is_return(char * name)
- {
- int i;
-
- TRACEP("is_return", printf("(%s)\n", name));
-
- for (i = 0;;i++) {
- if (rmn_tab[i] == NULL) {
- return FALSE;
- }
- else if (str_eq(rmn_tab[i], name)) {
- return TRUE;
- }
- }
- }
-
- /* Return TRUE if name is a Sherlock macro except RETURN_xxx. */
- bool
- is_sherlock(char * name)
- {
- int i;
-
- TRACEP("is_sherlock", printf("(%s)\n", name));
-
- /* Special cases, but not r_void. */
- if (str_eq(s_disable, name)) {
- return !disable_flag;
- }
- else if (str_eq(s_name, name)) {
- return !name_flag;
- }
-
- /* All other macros. */
- for (i = 0;;i++) {
- if (mn_tab[i] == NULL) {
- return FALSE;
- }
- else if (str_eq(mn_tab[i], name)) {
- return TRUE;
- }
- }
- }
-
- void
- out_char(int c)
- {
- if (skipping) {
- return;
- }
- else if (trigraph) {
- switch (c) {
- case '#': syssput("??="); break;
- case '[': syssput("??("); break;
- case '\\': syssput("??/"); break;
- case ']': syssput("??)"); break;
- case '^': syssput("??'"); break;
- case '{': syssput("??<"); break;
- case '|': syssput("??!"); break;
- case '}': syssput("??>"); break;
- case '~': syssput("??-"); break;
- default:
- syscput(c);
- }
- }
- else {
- syscput(c);
- }
- }
-
- /*
- Change the spelling of a Sherlock macro.
- */
- void
- set_syn(char * id1, char * id2)
- {
- int i;
-
- TRACEP("set_syn", printf("(%s, %s)\n", id1, id2));
-
- /* Special cases. */
- if (str_eq(id1, r_void)) {
- r_void = str_alloc(id2);
- return;
- }
- else if (str_eq(id1, s_disable)) {
- s_disable = str_alloc(id2);
- return;
- }
- else if (str_eq(id1, s_name)) {
- s_name = str_alloc(id2);
- return;
- }
-
- /* All return macros except RETURN_VOID. */
- for (i = 0; rmn_tab[i] != NULL; i++) {
- if (str_eq(rmn_tab[i], id1)) {
- rmn_tab[i] = str_alloc(id2);
- return;
- }
- }
-
- /* All other Sherlock macros. */
- for (i = 0; mn_tab[i] != NULL; i++) {
- if (str_eq(mn_tab[i], id1)) {
- mn_tab[i] = str_alloc(id2);
- return;
- }
- }
- printf("Synonym entry for %s has no effect.\n", id1);
- }
-
- void
- skip_bl(void)
- {
- while (ch == ' ' || ch == '\t') {
- sysnext();
- }
- }
-
- /*
- Allocate memory big enough to hold the string,
- then copy the string to the allocated memory.
- */
- char *
- str_alloc(char *s)
- {
- char * p;
- int n;
-
- TRACEPB("str_alloc", printf("(%s)\n", s));
-
- n = strlen(s) + 1;
- p = malloc(n);
- strcpy(p, s);
-
- RETURN_PTR("str_alloc", p);
- }
-
- void
- synonyms(void)
- {
- char buffer1 [1000];
- char buffer2 [1000];
-
- skip_bl();
- for(;;) {
- if (ch == END_FILE) {
- return;
- }
- else if (isid1(ch)) {
- get_id(&buffer1[0]);
- skip_bl();
- if (isid1(ch)) {
- get_id(&buffer2[0]);
- set_syn(&buffer1[0], &buffer2[0]);
- TRACEP("synonym",
- printf("<%s> = <%s>\n",
- buffer1, buffer2));
- skip_bl();
- if (ch == '\n') {
- sysnext();
- line++;
- skip_bl();
- }
- else {
- printf("%s: %d: Newline expected.\n",
- file, line);
- sysabort();
- }
- }
- else {
- printf("%s: %d: Synonym expected.\n",
- file, line);
- sysabort();
- }
- }
- else if (ch == ' ' || ch == '\t' || ch == '\n') {
- if (ch == '\n') {
- line++;
- }
- sysnext();
- }
- else if (ch == '#') {
- while (ch != '\n' && ch != END_FILE) {
- sysnext();
- }
- }
- else {
- printf("%s: %d: Identifier expected.\n",
- file, line);
- sysabort();
- }
- }
- }
-
- #ifdef MICRO_SOFT
- #include <fcntl.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #include <io.h>
- #endif
-
- #ifdef TURBOC
- #include <fcntl.h>
- #include <sys\stat.h>
- #include <io.h>
- #include <conio.h>
- #endif
-
- /*
- Variables used by system routines.
- */
- #define IBUF_SIZE 2048 /* Size of each input buffer. */
- #define OBUF_SIZE 2048 /* Size of the output buffer. */
-
- char * s_ip = NULL; /* input pointer. */
- int s_ic = 0; /* input count. */
- int s_ih = 0; /* input handle. */
- bool s_eof = FALSE; /* input EOF flag. */
- char s_npb = -1; /* Outer push-back. */
- char s_pushback = -1; /* Inner push-back char. */
-
- #define MAX_LINE 1000
- char s_buf [MAX_LINE]; /* Line buffer. */
- char * s_bufp = s_buf; /* Line buffer pointer. */
-
- char * s_op = NULL; /* output pointer. */
- int s_oc = ERROR; /* output count. */
- int s_oh = ERROR; /* output handle. */
-
- char ibuffer [IBUF_SIZE];
- char obuffer [OBUF_SIZE];
-
- /*
- Close all files and exit.
-
- Do not call sysabort() from inside
- sysiclose(), sysoclose(), or sys_release().
- */
- void
- sysabort(void)
- {
- TICK("sysabort");
-
- sysoclose();
- sysiclose();
- exit(BAD_EXIT);
- }
-
- /*
- ----- I N P U T L O G I C -----
-
- Set the global variable ch to the next character from the input stream.
- */
-
- void
- sysnext(void)
- {
- if (s_npb != -1) {
- ch = s_npb;
- s_npb = -1;
- return;
- }
- else if (s_eof) {
- ch = END_FILE;
- return;
- }
- for (;;) {
- ch = *s_bufp++;
- if (ch == '\0') {
- s_fillbuf();
- }
- else if (ch == END_FILE) {
- s_eof = TRUE;
- return;
- }
- else {
- return;
- }
- }
- }
-
- /* Fill the line buffer and delete lines consisting of #include "sl.h". */
- void
- s_fillbuf(void)
- {
- int c;
-
- for(s_bufp = s_buf; ;) {
- *s_bufp++ = c = sysn2();
- if (c == END_FILE || c == '\n') {
- break;
- }
- }
- *s_bufp = '\0';
- s_bufp = s_buf;
- if (include_flag && str_eq(s_bufp, "#include \"sl.h\"\n")) {
- line++;
- s_buf[0] = '\0';
- }
- }
-
- int
- sysn2(void)
- {
- int c;
-
- /* Delete all carriage returns. Translate all trigraph sequences. */
- do {
- c = sysn1();
-
- if (trigraph && c == '?') {
- c = sysn1();
- if (c == '?') {
- /* A trigraph sequence. */
- c = sysn1();
- switch (c) {
- case '=': c = '#'; break;
- case '(': c = '['; break;
- case '/': c = '\\'; break;
- case ')': c = ']'; break;
- case '\'': c = '^'; break;
- case '<': c = '{'; break;
- case '!': c = '|'; break;
- case '>': c = '}'; break;
- case '-': c = '~'; break;
- default:
-
- printf("line %d: unknown trigraph ignored: ??%c\n",
- line, c);
- c = '\r';
- }
- }
- else {
- s_pushback = c;
- c = '?';
- }
- }
- }
- while (c == '\r');
- return c;
- }
-
- int
- sysn1(void)
- {
- int n;
- int c;
-
- if (s_pushback != -1) {
- c = s_pushback;
- s_pushback = -1;
- return c;
- }
- else if (s_ic > 0) {
- s_ic--;
- return *s_ip++;
- }
- else {
- n = raw_read(s_ih, ibuffer, IBUF_SIZE);
- if (n > 0) {
- s_ic = n;
- s_ip = ibuffer;
- s_ic--;
- return *s_ip++;
- }
- else {
- return END_FILE;
- }
- }
- }
-
- /*
- Close the current input file.
- */
- void
- sysiclose(void)
- {
- TICK("sysiclose");
-
- /* Close the current input file. */
- if (s_ih != ERROR) {
- raw_close(s_ih);
- }
-
- ch = END_FILE;
- }
-
- /*
- Open a file for input.
- Return TRUE if all went well.
- */
- bool
- sysopen(char * name)
- {
- TRACEP("sysopen", printf("(%s)\n", name));
-
- /* Actually open the file. */
- s_ih = raw_open(name);
- if (s_ih == ERROR) {
- return FALSE;
- }
- else {
- s_eof = FALSE;
- s_ic = 0;
- s_ip = ibuffer;
- *s_bufp = '\0';
- sysnext();
- return TRUE;
- }
- }
-
- /*
- Close a file opened with raw_open() or raw_creat().
- */
- static void
- raw_close(int handle)
- {
- TRACEP("raw_close", printf("(%d)\n", handle));
-
- close (handle);
- }
-
- /*
- Open the file for writing only.
- Return a handle (int) or ERROR.
- */
- static int
- raw_creat(char * name)
- {
-
- TRACEP("raw_creat", printf("(%s)\n", name));
-
- #ifdef MICRO_SOFT
- chmod(name, S_IREAD | S_IWRITE);
- return creat(name, S_IREAD | S_IWRITE);
- #endif
-
- #ifdef TURBOC
- chmod(name, S_IREAD | S_IWRITE);
- return creat(name, S_IREAD | S_IWRITE);
- #endif
-
- }
-
- /*
- Open the file for reading only.
- Return a handle (int) or ERROR.
- */
- static int
- raw_open(char * name)
- {
- TRACEP("raw_open", printf("(%s)\n", name));
-
- return open(name, O_RDONLY | O_BINARY);
- }
-
- /*
- Read n bytes from the file described by handle into buffer[].
- Return the number of bytes read.
- */
- static int
- raw_read(int handle, char * buffer, int n)
- {
- int result;
-
- TRACEP("raw_read", printf("(handle: %d, buffer: %p, n: %d)\n",
- handle, buffer, n));
-
- result = read (handle, buffer, n);
- TRACEP("raw_read", printf("returns %d\n", result));
- return result;
- }
-
- /*
- Write n bytes from buffer[] to the file described by handle.
- Return the number of bytes written.
- */
- static int
- raw_write(int handle, char * buffer, int n)
- {
- TRACEP("raw_write", printf("(handle: %d, buffer: %p, n: %d)\n",
- handle, buffer, n));
-
- return write (handle, buffer, n);
- }
-
-
- /*
- ----- OUTPUT LOGIC -----
- */
-
- /*
- Open a file for output. Only one such file may be open at a time.
-
- Return TRUE if all went well.
- */
- bool
- syscreat(char * name)
- {
- TRACEP("syscreat", printf("(%s)\n", name));
-
- /* Actually open the file. */
- s_oh = raw_creat(name);
- if (s_oh == ERROR) {
- return FALSE;
- }
- else {
- /* The output buffer is empty. */
- s_oc = 0;
- s_op = obuffer;
- return TRUE;
- }
- }
-
- /*
- Close the output file(s).
- */
- void
- sysoclose(void)
- {
- TICK("sysoclose");
-
- if (s_oh != ERROR) {
- syscput(END_FILE);
- raw_write(s_oh, obuffer, s_oc);
- raw_close(s_oh);
- s_oh = ERROR;
- }
- }
-
- /*
- Put a newline to the output file.
- */
- void
- sysnlput(void)
- {
- STAT("sysnlput");
-
- /* syscput('\r'); bug fix: 11/9/88 */
- syscput('\n');
-
- /* Give user a chance to stop. */
- syscsts();
- }
-
- /*
- Put a non-newline to the output file.
- This is the most called routine after sysnext().
- */
- void
- syscput(char c)
- {
- TRACEP("syscput", printf("(%x = %c); s_oc=%d\n", c, c, s_oc));
-
- *s_op++ = c;
- s_oc++;
- if (s_oc == OBUF_SIZE) {
- if (raw_write(s_oh, obuffer, OBUF_SIZE) != OBUF_SIZE) {
- printf("Disk full\n");
- sysabort();
- return;
- }
- else {
- s_oc = 0;
- s_op = obuffer;
- }
- }
- }
-
- /*
- Put one string to the output file.
- */
- void
- syssput(char *s)
- {
- while (*s) {
- syscput(*s++);
- }
- }
-
- /*
- Return 0 if no character is ready from the keyboard.
- Otherwise, return the character itself.
- */
- static int
- syscstat(void)
- {
-
- #ifdef MICRO_SOFT
- if (kbhit()) {
- return fgetchar() & 0x7f;
- }
- else {
- return 0;
- }
- #endif
-
- #ifdef TURBOC
- if (kbhit()) {
- return fgetchar() & 0x7f;
- }
- else {
- return 0;
- }
- #endif
-
-
- }
-
- /*
- Get console status and pause if the user has hit control S.
- Abort if user has hit control C.
- */
-
- #define CONTROL_C 3
-
- void
- syscsts(void)
- {
- int c;
-
- c = syscstat();
-
- if (c == CONTROL_C) {
- printf("\nCompilation aborted by operator.\n");
- sysabort();
- }
- }
-